#include "stdafx.h"
#include "GraphTestReadingInformation.h"
#include <cmath>
#include "IReading.h"
#include "Reading.h"
#include "ITime.h"
#include "Time.h"
#include <list>
#include <set>
#include <memory>
#include <exception>
#include <string>


namespace Sensor {

	double GraphTestReadingInformation::getReadingValue(const int sensorId, const std::string readingType, const long int time) const {
	
		if (readingType != "Parent")
		{
			double value = 0;

			if (sensorId == 38 && readingType == "Temperature") {
				value += std::sin(2 * 3.14 * (time - 3600*2) / (3600.0 * 24.0)) * 10 + 50;
				value += std::sin(2 * 3.14 * (time) / (3600 * 7)) * 0.5;
				value += std::sin(2 * 3.14 * (time + 3600*.25) / (3600 * 2)) * 0.1;
				value += std::sin(2 * 3.14 * (time) / (3600 * 15) ) * 2;
				return value;
			}

			if (sensorId == 38) {
				value = std::sin(time / (60.0 * 60.0 * 6.0)) * 100;
			} else if (sensorId == 42) {
				value = std::cos(time / (60.0 * 60.0 * 12.0)) * 50;
			} else {
				value = std::sin(time / (60.0 * 60.0 * 3.0)) * 25 + std::sin(time / (60.0 * 60.0 * 6.0)) * 100;
			}

			if (readingType == "Temperature") {
				value += std::sin(time / (60.0 * 60.0 * 1.0)) * 10;
			} else if (readingType == "Moisture") {
				value -= std::sin(time / (60.0 * 60.0 * 1.0)) * 10;
			} else {
				value -= std::sin(time / (60.0 * 60.0 * 5.0)) * 25;
			}

			return value;
		}
		else
		{
			if (sensorId == 38)
			{
				return 38;
			}
			else if(sensorId == 42)
			{
				return 38;
			}
			else
			{
				return 38;
			}
		}
	}

	void GraphTestReadingInformation::update() {
	}

	std::list<std::unique_ptr<IReading>> GraphTestReadingInformation::getReading(const int sensorId, const std::string readingType, const ITime& start, const ITime& end) const {
		std::list<std::unique_ptr<IReading>> readings;

		std::set<std::string> readingTypes = getReadingTypes();
		if (readingTypes.find(readingType) != readingTypes.end()) { // Its one of the reading types that exists
			long int length = end.getDifferenceInSeconds(start);
		
			for (int i=0; i<length/readingInterval; i++) {
				long int readingTime = ((int) (start.getUnixTime() + i*readingInterval) / readingInterval) * readingInterval;

				std::unique_ptr<ITime> time( 
					new Time(readingTime)
					);

				readings.push_back(
					std::unique_ptr<IReading>(
						new Reading(
							sensorId,
							time,
							readingType,
							getReadingValue(sensorId, readingType, readingTime)
							)
						)
					);
			}
		}

		return readings;
	}

	std::set<std::string> GraphTestReadingInformation::getReadingTypes() const {
		std::set<std::string> readingTypes;
		readingTypes.insert("Temperature");
		readingTypes.insert("Moisture");
		readingTypes.insert("Voltage");
		readingTypes.insert("Parent");
		return readingTypes;
	}

	std::set<int> GraphTestReadingInformation::getSensorIds(const ITime& start, const ITime& end) const {
		std::set<int> ids;
		ids.insert(38);

		ids.insert(42);
		ids.insert(97);
		return ids;
	}

	void GraphTestReadingInformation::onReading(std::unique_ptr<IReading>& reading) {

	}

}
